package com.axend.sofa.viewmodel

import android.R
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import cn.com.heaton.blelibrary.ble.model.BleDevice
import cn.com.heaton.blelibrary.ble.utils.ByteUtils
import com.axend.lib_base.base.vm.BaseViewModel
import com.axend.lib_base.engine.toast.toast
import com.axend.lib_base.ext.toPlainFloatNoRounding
import com.axend.lib_base.help.ble.BleClient
import com.axend.lib_base.help.ble.BleMsgProcessor
import com.axend.lib_base.help.ble.enums.BleCommandTag
import com.axend.lib_base.utils.ByteUtil
import com.axend.lib_base.utils.CommUtils
import com.axend.lib_base.utils.DateUtils
import com.axend.lib_base.utils.log.MyLogUtils
import com.axend.lib_base.view.dialog.CustomCalibrationDialog
import com.axend.lib_room.entity.SofaLogEntity
import com.axend.lib_room.manager.LogManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext


class SensorViewModel : BaseViewModel() {

    /*是否选择了设备型号*/
    private var _isSelectModel: MutableLiveData<Boolean> = MutableLiveData(false)
    val isSelectModel: LiveData<Boolean> get() = _isSelectModel

    /*沙发门限1*/
    private var _sofaDoorThresh1: MutableLiveData<Float> = MutableLiveData()
    val sofaDoorThresh1: LiveData<Float> get() = _sofaDoorThresh1

    /*沙发门限2*/
    private var _sofaDoorThresh2: MutableLiveData<Float> = MutableLiveData()
    val sofaDoorThresh2: LiveData<Float> get() = _sofaDoorThresh2

    /*沙发型号 0未选型号*/
    private var _sofaModel: MutableLiveData<Int> = MutableLiveData(0)
    val sofaModel: LiveData<Int> get() = _sofaModel

    /*是否报警*/
    private var _isAlarm: MutableLiveData<Boolean> = MutableLiveData(false)
    val isAlarm: LiveData<Boolean> get() = _isAlarm

    /*固件版本*/
    private var _firmwareVersion: MutableLiveData<String> = MutableLiveData()
    val firmwareVersion: LiveData<String> get() = _firmwareVersion

    /*蓝牙固件版本*/
    private var _firmwareVersionBle: MutableLiveData<String> = MutableLiveData()
    val firmwareVersionBle: LiveData<String> get() = _firmwareVersionBle

    /**
     * dialogModel 0 loading 1 failed 2 success 3 dismiss
     */
    private var _dialogModel:MutableLiveData<Int> = MutableLiveData()
    val dialogModel: MutableLiveData<Int> get() = _dialogModel

    /*队列数据*/
    private val dataQueue = MutableSharedFlow<ByteArray>()

    /*持续性job*/
    private var commandJob: Job? = null
    private val startSendingFlow = MutableSharedFlow<UInt>()

    // 添加一个Job用于管理定时器
    private var alarmTimeoutJob: Job? = null


    /**
     * 写入ble指令
     */
    fun writeBleMsg(msg: ByteArray, originData: Any = "") {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                BleClient.writeData(msg, object : BleClient.OnBleWriteCallback {
                    override fun onWriteSuccess(device: BleDevice, data: ByteArray) {
                        /*写入成功后返回的消息处理*/
                        val msgPair = BleMsgProcessor.decodeFirmwareUpdateMsg(data)
//                        MyLogUtils.d(
//                            "解析后的字节内容：${ByteUtils.toHexString(msgPair?.second)}"
//                        )
                        msgPair?.let {
                            launchOnUI {
                                when (msgPair.first) {
                                    BleCommandTag.GET_VERSION -> {
                                        val version = byteArrayOf(
                                            msgPair.second[0],
                                            msgPair.second[1],
                                            msgPair.second[2],
                                            msgPair.second[3],
                                        )
                                        setFirmwareVersion(
                                            "V${
                                                com.axend.lib_base.utils.ByteUtils.byteArrayToCommaSeparatedString(
                                                    version
                                                )
                                            }"
                                        )
                                        MyLogUtils.d("version:$version")
                                    }

                                    BleCommandTag.GET_SOFA_DOOR_SILL -> {
                                        val doorThresh = ByteUtil.byte4ToFloatLittle(msgPair.second)
                                        if (doorThresh.isNaN()) return@launchOnUI
                                        setSofaDoorThresh1(doorThresh.toPlainFloatNoRounding())
                                    }

                                    BleCommandTag.GET_SOFA_DOOR_SILL2 -> {
                                        if (msgPair.second.size != 4) return@launchOnUI
                                        val doorThresh2 =
                                            ByteUtil.byte4ToFloatLittle(msgPair.second)
                                        val numberStr = ByteUtils.bytes2HexStr(msgPair.second)
                                        setSofaDoorThresh2(doorThresh2.toPlainFloatNoRounding())
                                    }

                                    BleCommandTag.GET_SOFA_MODEL -> {
                                        val sofaModel = ByteUtils.byte2int(msgPair.second)
                                        setSofaModel(sofaModel)
                                    }

                                    BleCommandTag.SET_SOFA_MODEL -> {
                                        when (msgPair.second[0]) {
                                            0.toByte() -> {
                                                toast(CommUtils.getString(com.axend.lib_base.R.string.app_tips_set_failed))
                                            }

                                            1.toByte() -> {
                                                if (originData is Int) {
                                                    setSofaModel(originData)
                                                }
                                                toast(CommUtils.getString(com.axend.lib_base.R.string.app_tips_set_success))
                                            }
                                        }
                                    }

                                    BleCommandTag.SET_SOFA_DOOR_SILL -> {
                                        when (msgPair.second[0]) {
                                            0.toByte() -> {
                                                toast(CommUtils.getString(com.axend.lib_base.R.string.app_tips_set_failed))
                                            }

                                            1.toByte() -> {
                                                if (originData is Float) {
                                                    setSofaDoorThresh1(originData.toPlainFloatNoRounding())
                                                }
                                                toast(CommUtils.getString(com.axend.lib_base.R.string.app_tips_set_success))
                                            }
                                        }
                                    }

                                    BleCommandTag.SET_SOFA_DOOR_SILL2 -> {
                                        when (msgPair.second[0]) {
                                            0.toByte() -> {
                                                toast(CommUtils.getString(com.axend.lib_base.R.string.app_tips_set_failed))
                                            }

                                            1.toByte() -> {
                                                if (originData is Float) {
                                                    setSofaDoorThresh2(originData.toPlainFloatNoRounding())
                                                }
                                                toast(CommUtils.getString(com.axend.lib_base.R.string.app_tips_set_success))
                                            }
                                        }
                                    }

                                    BleCommandTag.ALARM -> {
                                        if (msgPair.second.isEmpty()) return@launchOnUI
                                        val alarmCode = ByteUtil.bytes2IntLittle(msgPair?.second)
                                        setAlarm(alarmCode != 0)
                                        // 重置定时器
//                                        resetAlarmTimeout()
                                        /*添加日志*/
                                        viewModelScope.launch(Dispatchers.IO) {
                                            LogManager.saveLog(SofaLogEntity().apply {
                                                date = DateUtils.getCurrentTime()
                                                content = "${
                                                    msgPair?.first?.getMarkName().toString()
                                                } : $alarmCode"
                                            })
                                        }
                                    }

                                    BleCommandTag.STUDY_RESULT -> {
                                        loadHideProgress()
                                        setDialogModel(CustomCalibrationDialog.MODEL_SUCCESS)
                                        val thresh1Byte = byteArrayOf(msgPair.second[0], msgPair.second[1],
                                            msgPair.second[2], msgPair.second[3])
                                        val thresh2Byte = byteArrayOf(msgPair.second[4], msgPair.second[5],
                                            msgPair.second[6], msgPair.second[7])
                                        MyLogUtils.w("thresh1Byte:${ByteUtil.byte4ToFloatLittle(thresh1Byte)}" +
                                                ",thresh2Byte:${ByteUtil.byte4ToFloatLittle(thresh2Byte)}")
                                        setSofaDoorThresh1(ByteUtil.byte4ToFloatLittle(thresh1Byte))
                                        setSofaDoorThresh2(ByteUtil.byte4ToFloatLittle(thresh2Byte))
                                    }

                                    BleCommandTag.SET_STUDY_START -> {
                                        when (msgPair.second[0]) {
                                            0.toByte() -> {
                                                loadHideProgress()
                                                setDialogModel(CustomCalibrationDialog.MODEL_FAILED)
                                            }

                                            1.toByte() -> {
//                                                setDialogModel(CustomCalibrationDialog.MODEL_LOADING)
                                                loadStartCalibration()
                                            }
                                        }
                                    }
                                    BleCommandTag.SET_STUDY_END -> {
                                        when (msgPair.second[0]) {
                                            0.toByte() -> {
                                                loadHideProgress()
                                                setDialogModel(CustomCalibrationDialog.MODEL_FAILED)
                                            }

                                            1.toByte() -> {
                                                loadHideProgress()
                                                setDialogModel(CustomCalibrationDialog.MODEL_DISMISS)
                                            }
                                        }
                                    }

                                    else -> {

                                    }
                                }
                            }
                        }
//                        launchOnUI {
//                            loadSuccess()
//                        }
                    }

                    override fun onWriteFailed(device: BleDevice, errorCode: Int) {
                        loadError("$errorCode")
                    }

                })
            }
        }
    }

    /*创建队列数据*/
    fun initAndSendDataQueue() {
//        loadStartLoading()
        /*获取厂商蓝牙固件版本*/
        viewModelScope.launch {
            listOf(
                BleMsgProcessor.encodeMsg(
                    BleCommandTag.GET_VERSION.getMarkFixCommand(),
                    BleCommandTag.GET_VERSION
                ),
                BleMsgProcessor.encodeMsg(
                    BleCommandTag.GET_SOFA_MODEL.getMarkFixCommand(),
                    BleCommandTag.GET_SOFA_MODEL
                ),
                BleMsgProcessor.encodeMsg(
                    BleCommandTag.GET_SOFA_DOOR_SILL.getMarkFixCommand(),
                    BleCommandTag.GET_SOFA_DOOR_SILL
                ),
                BleMsgProcessor.encodeMsg(
                    BleCommandTag.GET_SOFA_DOOR_SILL2.getMarkFixCommand(),
                    BleCommandTag.GET_SOFA_DOOR_SILL2
                ),
            ).forEach {
                delay(600)
                dataQueue.emit(it)
            }

        }

        viewModelScope.launch {
            try {
                dataQueue.collect { message ->
                    writeBleMsg(message)
                }
            } catch (e: Exception) {
                MyLogUtils.e("Error in dataQueue collection: ${e.message}")
            }
        }

        BleClient.readDeviceInformationChaByUUID(BleClient.BLUETOOTH_FIRMWARE_VERSION_READ_UUID){
                uuid, data ->
            setBluetoothFirmwareVersion("V${ByteUtils.toString(data)}")
        }

    }

    /**
     * 沙发上升
     */
    fun bleSofaAction(action: UInt) {
        writeBleMsg(BleMsgProcessor.encodeMsg(action, BleCommandTag.SET_SOFA_ACTION))
    }


    /**
     * 沙发上升长按
     */
    fun bleSofaActionLong(action: UInt) {
        commandJob = viewModelScope.launch {
            startSendingFlow.collect { action ->
                while (true) {
                    writeBleMsg(BleMsgProcessor.encodeMsg(action, BleCommandTag.SET_SOFA_ACTION))
                    delay(1000)
                }
            }
        }
        viewModelScope.launch {
            startSendingFlow.emit(action)
        }
    }

    /**
     * 停止沙发长按任务
     */
    fun bleStopSofaActionLong() {
        launchOnUI {
            commandJob?.cancel()
        }
    }


    /**
     * 设置沙发门限1
     */
    fun setSofaDoorThresh1(thresh: Float) {
        launchOnUI {
            _sofaDoorThresh1.postValue(thresh)
        }
    }


    /**
     * 设置沙发门限2
     */
    fun setSofaDoorThresh2(thresh: Float) {
        launchOnUI {
            _sofaDoorThresh2.postValue(thresh)
        }
    }

    /**
     * 设置报警
     */
    fun setAlarm(alarm: Boolean) {
        launchOnUI {
            _isAlarm.postValue(alarm)
        }
    }


    /**
     * 设置固件版本
     */
    fun setFirmwareVersion(version: String) {
        launchOnUI {
            _firmwareVersion.postValue(version)
        }
    }


    /**
     * 设置沙发型号
     */
    fun setSofaModel(model: Int) {
        launchOnUI {
            _sofaModel.postValue(model)
        }
    }

    /**
     * 设置蓝牙固件版本
     */
    private fun setBluetoothFirmwareVersion(version: String) {
        launchOnUI {
            _firmwareVersionBle.postValue(version)
        }
    }

    /**
     * 设置dialogModel
     */
    fun setDialogModel(model: Int) {
        launchOnUI {
            _dialogModel.postValue(model)
        }
    }

    fun getMarginTop(): Int {
        return if (sofaModel.value == 0) com.axend.sofa.R.dimen.margin_top_dp40 else com.axend.sofa.R.dimen.margin_top_dp0
    }

    // 重置定时器的方法
    private fun resetAlarmTimeout() {
        // 取消之前的定时器
        alarmTimeoutJob?.cancel()
        // 启动新的定时器
        alarmTimeoutJob = viewModelScope.launch {
            delay(5000) // 5秒
            setAlarm(false)
        }
    }
}
